import ROSLIB from 'roslib';

export function createCameraService(ros, handlers) {
  const { onImageData, addLog } = handlers || {};
  let imageTopic = null;
  let canvas = null;
  let ctx = null;
  let lastDrawAtMs = 0;
  const MAX_FPS = 8; // 进一步降低帧率以减少延迟
  let fillMode = 'cover'; // 'cover' 填满画布, 'contain' 等比缩放

  // 创建图像话题订阅
  const subscribeToCamera = () => {
    if (!ros) {
      addLog && addLog('ROS连接未建立，无法订阅摄像头话题', 'error');
      return;
    }

    try {
      imageTopic = new ROSLIB.Topic({
        ros: ros,
        name: '/robot/front_camera/image_raw',
        messageType: 'sensor_msgs/msg/Image'
      });

      imageTopic.subscribe(handleImageMessage);
      addLog && addLog('前置摄像头话题订阅成功', 'success');
    } catch (error) {
      addLog && addLog(`摄像头话题订阅失败: ${error?.message || error}`, 'error');
    }
  };

  // 处理图像消息
  const handleImageMessage = (message) => {
    try {
      if (!message || !message.data) {
        return;
      }

      // 将ROS图像数据转换为ImageData
      const imageData = convertROSImageToImageData(message);
      if (imageData && canvas && ctx) {
        // 渲染到canvas
        renderImageToCanvas(imageData);
        onImageData && onImageData(imageData);
      } else if (!imageData) {
        // 首帧打印信息帮助排查
        try {
          const { width, height, encoding } = message || {};
          addLog && addLog(`摄像头首帧无法解码，编码=${encoding} 尺寸=${width}x${height}`, 'warning');
        } catch (e) {
          // 避免因消息格式异常导致崩溃
          addLog && addLog('摄像头首帧信息记录失败', 'warning');
        }
      }
    } catch (error) {
      addLog && addLog(`图像处理失败: ${error?.message || error}`, 'error');
    }
  };

  // 将可能的base64字符串转换为Uint8Array
  const decodeToUint8Array = (raw) => {
    if (raw == null) return null;
    if (raw instanceof Uint8Array) return raw;
    if (Array.isArray(raw)) return new Uint8Array(raw);
    if (typeof raw === 'string') {
      // base64 -> binary string -> Uint8Array
      try {
        const binary = atob(raw);
        const len = binary.length;
        const bytes = new Uint8Array(len);
        for (let i = 0; i < len; i++) bytes[i] = binary.charCodeAt(i);
        return bytes;
      } catch (e) {
        addLog && addLog(`base64解码失败: ${e?.message || e}`, 'warning');
        return null;
      }
    }
    // Fallback
    try {
      return new Uint8Array(raw);
    } catch {
      return null;
    }
  };

  // 转换ROS图像消息为ImageData
  const convertROSImageToImageData = (message) => {
    try {
      const { width, height, encoding, data } = message;
      
      if (!width || !height || !data) {
        return null;
      }

      const src = decodeToUint8Array(data);
      if (!src) return null;

      // 根据编码格式处理图像数据
      const out = new ImageData(width, height);
      const dst = out.data; // Uint8ClampedArray，长度 = w*h*4

      if (encoding === 'rgb8') {
        // src: R G B, dst: R G B A
        for (let i = 0, j = 0; i < src.length; i += 3, j += 4) {
          dst[j] = src[i];
          dst[j + 1] = src[i + 1];
          dst[j + 2] = src[i + 2];
          dst[j + 3] = 255;
        }
      } else if (encoding === 'bgr8') {
        for (let i = 0, j = 0; i < src.length; i += 3, j += 4) {
          dst[j] = src[i + 2];     // R = B
          dst[j + 1] = src[i + 1]; // G
          dst[j + 2] = src[i];     // B = R
          dst[j + 3] = 255;        // A
        }
      } else if (encoding === 'mono8') {
        for (let i = 0, j = 0; i < src.length; i++, j += 4) {
          const gray = src[i];
          dst[j] = gray;
          dst[j + 1] = gray;
          dst[j + 2] = gray;
          dst[j + 3] = 255;
        }
      } else if (encoding === 'rgba8') {
        // 直接拷贝（长度应为 w*h*4）
        dst.set(src.subarray(0, dst.length));
      } else if (
        encoding === 'yuv422' ||
        encoding === 'yuv422_yuy2' ||
        encoding === 'yuyv' ||
        encoding === 'uyvy'
      ) {
        // YUV422 两像素打包: Y0 U Y1 V (YUYV) 或 U Y0 V Y1 (UYVY)
        let offset = 0;
        const isUYVY = encoding === 'uyvy';
        for (let j = 0; j < height; j++) {
          for (let i = 0; i < width; i += 2) {
            let Y0, U, Y1, V;
            if (isUYVY) {
              U = src[offset++];
              Y0 = src[offset++];
              V = src[offset++];
              Y1 = src[offset++];
            } else {
              Y0 = src[offset++];
              U = src[offset++];
              Y1 = src[offset++];
              V = src[offset++];
            }

            const [r0, g0, b0] = yuvToRgb(Y0, U, V);
            const [r1, g1, b1] = yuvToRgb(Y1, U, V);

            let p = (j * width + i) * 4;
            dst[p++] = r0; dst[p++] = g0; dst[p++] = b0; dst[p++] = 255;
            dst[p++] = r1; dst[p++] = g1; dst[p++] = b1; dst[p++] = 255;
          }
        }
      } else {
        addLog && addLog(`不支持的图像编码格式: ${encoding}`, 'warning');
        return null;
      }

      return out;
    } catch (error) {
      addLog && addLog(`图像数据转换失败: ${error?.message || error}`, 'error');
      return null;
    }
  };

  // YUV 转 RGB（BT.601 近似）
  const clamp = (v) => (v < 0 ? 0 : v > 255 ? 255 : v);
  const yuvToRgb = (y, u, v) => {
    const c = y - 16;
    const d = u - 128;
    const e = v - 128;
    let r = (298 * c + 409 * e + 128) >> 8;
    let g = (298 * c - 100 * d - 208 * e + 128) >> 8;
    let b = (298 * c + 516 * d + 128) >> 8;
    return [clamp(r), clamp(g), clamp(b)];
  };

  // 渲染图像到canvas
  const renderImageToCanvas = (imageData) => {
    if (!canvas || !ctx) return;

    try {
      // 帧率限制
      const now = performance.now();
      const minInterval = 1000 / MAX_FPS;
      if (now - lastDrawAtMs < minInterval) {
        return; // 丢弃过密的帧
      }
      lastDrawAtMs = now;

      // 同步实际像素大小到canvas，确保完全填满
      const containerWidth = canvas.clientWidth;
      const containerHeight = canvas.clientHeight;
      
      if (canvas.width !== containerWidth || canvas.height !== containerHeight) {
        canvas.width = containerWidth;
        canvas.height = containerHeight;
      }

      // 计算缩放比例 - 强制填满画布
      const scaleX = containerWidth / imageData.width;
      const scaleY = containerHeight / imageData.height;
      const scale = Math.max(scaleX, scaleY); // 强制使用 cover 模式

      const scaledWidth = Math.round(imageData.width * scale);
      const scaledHeight = Math.round(imageData.height * scale);

      // 计算绘制区域，确保完全填满画布
      const drawX = (containerWidth - scaledWidth) / 2;
      const drawY = (containerHeight - scaledHeight) / 2;

      // 清空canvas
      ctx.clearRect(0, 0, canvas.width, canvas.height);

      // 创建临时canvas进行缩放
      const tempCanvas = document.createElement('canvas');
      const tempCtx = tempCanvas.getContext('2d');
      tempCanvas.width = imageData.width;
      tempCanvas.height = imageData.height;
      tempCtx.putImageData(imageData, 0, 0);

      // 使用更高效的绘制方式，禁用平滑
      ctx.imageSmoothingEnabled = false;
      ctx.drawImage(tempCanvas, drawX, drawY, scaledWidth, scaledHeight);
    } catch (error) {
      addLog && addLog(`Canvas渲染失败: ${error?.message || error}`, 'error');
    }
  };

  // 设置canvas
  const setCanvas = (canvasElement) => {
    canvas = canvasElement;
    if (canvas) {
      ctx = canvas.getContext('2d');
    }
  };

  // 取消订阅
  const unsubscribe = () => {
    try {
      if (imageTopic) {
        imageTopic.unsubscribe();
        imageTopic = null;
      }
      addLog && addLog('摄像头话题已取消订阅', 'info');
    } catch (error) {
      addLog && addLog(`摄像头取消订阅失败: ${error?.message || error}`, 'warning');
    }
  };

  // 切换显示模式
  const setFillMode = (mode) => {
    fillMode = mode === 'cover' ? 'cover' : 'contain';
    addLog && addLog(`显示模式切换为: ${fillMode}`, 'info');
  };

  return {
    subscribeToCamera,
    setCanvas,
    setFillMode,
    unsubscribe
  };
}
